#import <Foundation/Foundation.h>

template <typename ID>
class SharedPtr
{
    public:
        ~SharedPtr()
        {
//                NSLog(@"Releasing object");
                //if (m_id != nil)
                        [m_id release];
        }
        SharedPtr() :  m_id(nil)
        {
        }
        SharedPtr(id newId) :  m_id(newId)
        {
/*                if (newId != nil) {
                       [m_id retain];
                }*/
        }
        SharedPtr(const SharedPtr& ptr) :  m_id(ptr.data())
        {
                [m_id retain];
        }

        const SharedPtr& operator=(id newId)
        {
                if (m_id != newId) {
                        if (m_id != nil) [m_id release];
                         m_id = newId;
//                        [m_id retain];
                }
                return (*this);
        }
        const SharedPtr& operator=(const SharedPtr& ptr)
        {
                if (m_id != ptr.data()) {
                        if (m_id != nil) [m_id release];
                         m_id = ptr.data();
                        [m_id retain];
                }
                return (*this);
        }

        ID* data() const
        {
                return m_id;
        }
        operator id()
        {
                return m_id;
        }
    private:
        ID* m_id;
};




@interface HelloWorld : NSObject
- (void) hello;
@end

@implementation HelloWorld
- (void) hello: (int)n {
    NSLog(@"hello world! %@ %d", [self description], n);
}
- (void) dealloc {
    NSLog(@"Dealloc hello world! %@", [self description]);
    [super dealloc];
}
@end




int main(void) 
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    SharedPtr<HelloWorld> shw ( [[HelloWorld alloc] init] );

    HelloWorld *hw = [[HelloWorld alloc] init];
    [hw hello:2];

        {
            SharedPtr<HelloWorld> shw2;
            shw2 = shw;
            [shw2 hello:1];
            shw2 = [[HelloWorld alloc] init];
            shw2 = [[HelloWorld alloc] init];
            shw2 = [[HelloWorld alloc] init];
            shw2 = [[HelloWorld alloc] init];
            [shw2 hello:3];
        }
    [shw hello:1];

//    [shw release];
    [hw release];
    [pool drain];
//    [pool release];
    return 0;
}



